package proxy

import (
	"bufio"
	"bytes"
	"fmt"
	"net"
	"net/http"
	"net/url"
	"strings"
	"time"

	"network-firewall-go/internal/types"
	"network-firewall-go/internal/utils"

	"golang.org/x/net/http2"
)

// handleHTTPRequest 处理HTTP请求的入口
func (s *Server) handleHTTPRequest(w http.ResponseWriter, r *http.Request) {
	fmt.Printf("🔍 收到请求: %s %s %s\n", r.Method, r.Host, r.URL.String())
	fmt.Printf("🔍 请求头: %+v\n", r.Header)
	fmt.Printf("🔍 请求URL: %+v\n", r.URL)
	fmt.Printf("🔍 请求Host: %s\n", r.Host)
	fmt.Printf("🔍 请求RemoteAddr: %s\n", r.RemoteAddr)
	fmt.Printf("🔍 请求协议: %s\n", r.Proto)

	// 检查是否是CONNECT请求（用于HTTPS隧道）
	if r.Method == "CONNECT" {
		fmt.Printf("🔗 ✅ 识别到CONNECT请求: %s\n", r.Host)
		s.handleConnectRequest(w, r)
		return
	}

	fmt.Printf("📨 处理普通HTTP请求: %s %s\n", r.Method, r.URL.String())
	// 处理普通HTTP请求
	s.handleProxyRequest(w, r, false)
}

// handleProxyRequest 处理代理请求
func (s *Server) handleProxyRequest(w http.ResponseWriter, r *http.Request, isHTTPS bool) {
	startTime := time.Now()

	// 生成请求ID
	requestID := utils.GenerateRequestID()

	fmt.Printf("📨 %s请求: %s %s (协议: %s)\n",
		func() string {
			if isHTTPS {
				return "HTTPS"
			} else {
				return "HTTP"
			}
		}(),
		r.Method, r.URL.String(), r.Proto)

	// 🔍 只有当URL包含特定路径时才输出原始请求的完整信息
	if strings.Contains(r.URL.Path, "/oauth/wechat/dewatermark") {
		fmt.Printf("🔍 ========== 原始请求RAW数据 ==========\n")
		fmt.Printf("🔍 Method: %s\n", r.Method)
		fmt.Printf("🔍 URL: %s\n", r.URL.String())
		fmt.Printf("🔍 Proto: %s\n", r.Proto)
		fmt.Printf("🔍 ProtoMajor: %d\n", r.ProtoMajor)
		fmt.Printf("🔍 ProtoMinor: %d\n", r.ProtoMinor)
		fmt.Printf("🔍 Host: %s\n", r.Host)
		fmt.Printf("🔍 RemoteAddr: %s\n", r.RemoteAddr)
		fmt.Printf("🔍 RequestURI: %s\n", r.RequestURI)
		fmt.Printf("🔍 TLS: %v\n", r.TLS != nil)
		if r.TLS != nil {
			fmt.Printf("🔍 TLS Version: %d\n", r.TLS.Version)
		}
		fmt.Printf("🔍 Headers (%d total):\n", len(r.Header))
		for key, values := range r.Header {
			for _, value := range values {
				fmt.Printf("🔍   %s: %s\n", key, value)
			}
		}
		fmt.Printf("🔍 ========================================\n")
	}

	// 读取请求体
	body, err := utils.ReadRequestBody(r)
	if err != nil {
		fmt.Printf("❌ 读取请求体失败: %v\n", err)
		http.Error(w, "Failed to read request body", http.StatusInternalServerError)
		return
	}

	// 创建HTTP请求对象
	httpReq := types.NewHTTPRequest(r)
	httpReq.ID = requestID
	httpReq.Body = string(body)
	httpReq.BodySize = int64(len(body))

	// 🔍 只有当URL包含特定路径时才输出转换后的请求对象
	if strings.Contains(r.URL.Path, "/oauth/wechat/dewatermark") {
		fmt.Printf("🔍 ========== 转换后的请求对象 ==========\n")
		fmt.Printf("🔍 HTTPRequest.HTTPVersion: %s\n", httpReq.HTTPVersion)
		fmt.Printf("🔍 HTTPRequest.Method: %s\n", httpReq.Method)
		fmt.Printf("🔍 HTTPRequest.URL: %s\n", httpReq.URL)
		fmt.Printf("🔍 HTTPRequest.Host: %s\n", httpReq.Host)
		fmt.Printf("🔍 HTTPRequest.Headers (转换后):\n")
		for key, value := range httpReq.Headers {
			fmt.Printf("🔍   %s: %s\n", key, value)
		}
		fmt.Printf("🔍 ========================================\n")
	}

	// 获取TLS信息
	if isHTTPS && r.TLS != nil {
		httpReq.TLSVersion = utils.GetTLSVersion(r.TLS.Version)
	}

	// 创建新的请求对象（避免RequestURI问题）
	targetURL := r.URL
	if !targetURL.IsAbs() {
		// 如果URL不是绝对路径，构建完整URL
		scheme := "http"
		if isHTTPS {
			scheme = "https"
		}
		targetURL = &url.URL{
			Scheme:   scheme,
			Host:     r.Host,
			Path:     r.URL.Path,
			RawQuery: r.URL.RawQuery,
			Fragment: r.URL.Fragment,
		}
	}

	// 创建新的请求
	newReq, err := http.NewRequest(r.Method, targetURL.String(), bytes.NewReader(body))
	if err != nil {
		fmt.Printf("❌ 创建请求失败: %v\n", err)
		s.recordFailedTransaction(httpReq, startTime, err)
		http.Error(w, "Failed to create request", http.StatusInternalServerError)
		return
	}

	// 完全复制原始请求头，不做任何修改，并确保添加必需的头部
	isDebugURL := strings.Contains(r.URL.Path, "/oauth/wechat/dewatermark")
	if isDebugURL {
		fmt.Printf("🔍 原始请求头数量: %d\n", len(r.Header))
		fmt.Printf("🔍 请求协议: %s\n", r.Proto)
	}

	// 特别保存priority头部（如果存在）
	var priorityHeader []string
	if priority := r.Header.Get("priority"); priority != "" {
		priorityHeader = r.Header["priority"] // 获取所有priority值
		if isDebugURL {
			fmt.Printf("🔍 发现Priority头部: %v\n", priorityHeader)
		}
	}

	// 先复制所有原始请求头
	for key, values := range r.Header {
		if isDebugURL {
			fmt.Printf("🔍 原始请求头: %s = %v\n", key, values)
		}
		for _, value := range values {
			newReq.Header.Add(key, value)
		}
	}

	// 确保priority头部被正确设置（强制重新设置以防丢失）
	if len(priorityHeader) > 0 {
		newReq.Header.Del("priority") // 先删除
		for _, value := range priorityHeader {
			newReq.Header.Add("priority", value) // 重新添加
		}
		if isDebugURL {
			fmt.Printf("🔍 强制重新设置Priority头部: %v\n", newReq.Header["priority"])
		}
	}

	// 确保host头部存在（某些客户端可能不发送Host头但设置了r.Host）
	if r.Host != "" && newReq.Header.Get("Host") == "" {
		newReq.Header.Set("Host", r.Host)
		if isDebugURL {
			fmt.Printf("🔍 补充Host请求头: %s\n", r.Host)
		}
	}

	if isDebugURL {
		fmt.Printf("🔍 转发请求头数量: %d\n", len(newReq.Header))
		fmt.Printf("🔍 最终Priority头部: %v\n", newReq.Header["priority"])
	}

	// 创建支持HTTP/2的HTTP客户端
	transport := &http.Transport{
		DisableKeepAlives: false,
		IdleConnTimeout:   90 * time.Second,
		// 配置DNS解析
		DialContext: (&net.Dialer{
			Timeout:   30 * time.Second,
			KeepAlive: 30 * time.Second,
			// 优先使用IPv4，避免IPv6 DNS解析问题
			FallbackDelay: 300 * time.Millisecond,
		}).DialContext,
	}

	// 启用HTTP/2支持
	if err := http2.ConfigureTransport(transport); err != nil {
		fmt.Printf("⚠️ 配置HTTP/2传输失败: %v\n", err)
	}

	client := &http.Client{
		Timeout:   30 * time.Second,
		Transport: transport,
	}

	// 发送请求
	resp, err := client.Do(newReq)
	if err != nil {
		fmt.Printf("❌ 请求失败: %v\n", err)
		s.recordFailedTransaction(httpReq, startTime, err)
		http.Error(w, "Proxy request failed", http.StatusBadGateway)
		return
	}
	defer resp.Body.Close()

	fmt.Printf("✅ 收到响应: %s %d (协议: %s)\n", resp.Status, resp.StatusCode, resp.Proto)

	// 🔍 只有当URL包含特定路径时才输出原始响应的完整信息
	if isDebugURL {
		fmt.Printf("🔍 ========== 原始响应RAW数据 ==========\n")
		fmt.Printf("🔍 Status: %s\n", resp.Status)
		fmt.Printf("🔍 StatusCode: %d\n", resp.StatusCode)
		fmt.Printf("🔍 Proto: %s\n", resp.Proto)
		fmt.Printf("🔍 ProtoMajor: %d\n", resp.ProtoMajor)
		fmt.Printf("🔍 ProtoMinor: %d\n", resp.ProtoMinor)
		fmt.Printf("🔍 TLS: %v\n", resp.TLS != nil)
		if resp.TLS != nil {
			fmt.Printf("🔍 TLS Version: %d\n", resp.TLS.Version)
		}
		fmt.Printf("🔍 Headers (%d total):\n", len(resp.Header))
		for key, values := range resp.Header {
			for _, value := range values {
				fmt.Printf("🔍   %s: %s\n", key, value)
			}
		}
		fmt.Printf("🔍 ========================================\n")
	}

	// 读取响应体
	respBody, err := utils.ReadResponseBody(resp)
	if err != nil {
		fmt.Printf("❌ 读取响应体失败: %v\n", err)
		http.Error(w, "Failed to read response body", http.StatusInternalServerError)
		return
	}

	// 保存原始响应体（用于返回给客户端）
	originalRespBody := make([]byte, len(respBody))
	copy(originalRespBody, respBody)

	// 处理响应体解压（仅用于记录到数据库）
	decompressedBody := respBody
	contentEncoding := resp.Header.Get("Content-Encoding")
	if contentEncoding != "" {
		if decompressed, err := utils.DecompressResponse(respBody, contentEncoding); err == nil {
			decompressedBody = decompressed
			fmt.Printf("✅ 响应体已解压用于记录: %s -> %d bytes (原始: %d bytes)\n",
				contentEncoding, len(decompressedBody), len(originalRespBody))
		} else {
			fmt.Printf("⚠️ 响应体解压失败: %v\n", err)
		}
	}

	// 创建HTTP响应对象（使用解压后的内容用于记录）
	httpResp := types.NewHTTPResponse(resp, requestID)
	httpResp.ID = utils.GenerateResponseID()
	httpResp.Body = utils.FormatBodyForDisplay(decompressedBody, resp.Header.Get("Content-Type"), 10000)
	httpResp.BodySize = int64(len(decompressedBody))

	// 🔍 只有当URL包含特定路径时才输出转换后的响应对象
	if isDebugURL {
		fmt.Printf("🔍 ========== 转换后的响应对象 ==========\n")
		fmt.Printf("🔍 HTTPResponse.HTTPVersion: %s\n", httpResp.HTTPVersion)
		fmt.Printf("🔍 HTTPResponse.StatusCode: %d\n", httpResp.StatusCode)
		fmt.Printf("🔍 HTTPResponse.StatusText: %s\n", httpResp.StatusText)
		fmt.Printf("🔍 HTTPResponse.Headers (转换后):\n")
		for key, value := range httpResp.Headers {
			fmt.Printf("🔍   %s: %s\n", key, value)
		}
		fmt.Printf("🔍 ========================================\n")
	}

	// 获取TLS信息
	if isHTTPS && resp.TLS != nil {
		httpResp.TLSVersion = utils.GetTLSVersion(resp.TLS.Version)
	}

	// 创建事务
	transaction := types.NewHTTPTransaction(httpReq, httpResp)
	transaction.ID = utils.GenerateTransactionID()
	transaction.Duration = time.Since(startTime).Milliseconds()

	// 🔍 只有当URL包含特定路径时才输出最终事务对象
	if isDebugURL {
		fmt.Printf("🔍 ========== 最终事务对象 ==========\n")
		fmt.Printf("🔍 Transaction.ID: %s\n", transaction.ID)
		fmt.Printf("🔍 Transaction.Duration: %d ms\n", transaction.Duration)
		fmt.Printf("🔍 Transaction.Request.HTTPVersion: %s\n", transaction.Request.HTTPVersion)
		fmt.Printf("🔍 Transaction.Response.HTTPVersion: %s\n", transaction.Response.HTTPVersion)
		fmt.Printf("🔍 Transaction.Response.StatusCode: %d\n", transaction.Response.StatusCode)
		fmt.Printf("🔍 ===================================\n")
	}

	// 执行规则
	if s.rulesEngine != nil {
		s.wg.Add(1)
		go func() {
			defer s.wg.Done()
			s.executeRules(transaction)
		}()
	}

	// 保存事务到数据库
	if s.db != nil {
		s.wg.Add(1)
		go func() {
			defer s.wg.Done()
			if err := s.db.SaveTransaction(transaction); err != nil {
				fmt.Printf("❌ 保存事务失败: %v\n", err)
			} else {
				fmt.Printf("✅ 事务已保存到数据库: %s\n", transaction.ID)
			}
		}()
	}

	// 通过WebSocket发送实时更新
	if s.wsServer != nil {
		s.wsServer.BroadcastTransaction(transaction)
		fmt.Printf("📡 事务已通过WebSocket广播: %s\n", transaction.ID)
	}

	// 复制响应头到客户端（保持原始格式）
	for key, values := range resp.Header {
		for _, value := range values {
			w.Header().Add(key, value)
		}
	}

	// 设置状态码
	w.WriteHeader(resp.StatusCode)

	// 返回原始响应体给客户端
	if _, err := w.Write(originalRespBody); err != nil {
		fmt.Printf("❌ 写入响应体失败: %v\n", err)
	}

	fmt.Printf("✅ 请求处理完成: %s %s (耗时: %dms)\n",
		r.Method, r.URL.String(), time.Since(startTime).Milliseconds())
}

// executeRules 执行规则
func (s *Server) executeRules(transaction *types.HTTPTransaction) {
	ctx := &types.RequestContext{
		Request:     transaction.Request,
		Response:    transaction.Response,
		Transaction: transaction,
		StartTime:   time.Unix(transaction.Request.Timestamp/1000, 0),
		EndTime:     time.Unix(transaction.Response.Timestamp/1000, 0),
	}

	results := s.rulesEngine.ExecuteRules(ctx)

	// 记录规则执行结果
	for _, result := range results {
		if result.Error != "" {
			fmt.Printf("⚠️ 规则执行失败 [%s]: %s\n", result.RuleID, result.Error)
		} else if result.Executed {
			fmt.Printf("✅ 规则执行成功 [%s]\n", result.RuleID)
		}
	}
}

// recordFailedTransaction 记录失败的事务
func (s *Server) recordFailedTransaction(req *types.HTTPRequest, startTime time.Time, err error) {
	resp := &types.HTTPResponse{
		ID:         utils.GenerateResponseID(),
		RequestID:  req.ID,
		StatusCode: 0,
		StatusText: "Request Failed",
		Headers:    make(map[string]string),
		Cookies:    make(map[string]string),
		Body:       fmt.Sprintf("请求失败: %v", err),
		Timestamp:  time.Now().UnixMilli(),
	}

	transaction := types.NewHTTPTransaction(req, resp)
	transaction.ID = utils.GenerateTransactionID()
	transaction.Duration = time.Since(startTime).Milliseconds()
	transaction.Error = err.Error()

	// 保存到数据库
	if s.db != nil {
		go func() {
			if err := s.db.SaveTransaction(transaction); err != nil {
				fmt.Printf("❌ 保存失败事务失败: %v\n", err)
			}
		}()
	}

	// 通过WebSocket广播
	if s.wsServer != nil {
		go s.wsServer.BroadcastTransaction(transaction)
	}

	// 更新统计信息（这里可以添加错误计数字段）
	s.stats.mu.Lock()
	// s.stats.errors++ // 需要在ServerStats中添加这个字段
	s.stats.mu.Unlock()
}

// handleHTTPRequestTCP 处理TCP连接的HTTP请求
func (s *Server) handleHTTPRequestTCP(clientConn net.Conn, req *http.Request) {
	fmt.Printf("🌐 处理HTTP请求: %s %s\n", req.Method, req.URL.String())

	// 如果URL没有scheme，说明是代理请求，需要解析完整URL
	if req.URL.Scheme == "" {
		// 从Host头获取目标地址
		if req.Host == "" {
			fmt.Printf("❌ 无效的HTTP请求: 缺少Host头\n")
			s.sendHTTPError(clientConn, 400, "Bad Request")
			return
		}

		// 构建完整URL
		scheme := "http"
		fullURL := fmt.Sprintf("%s://%s%s", scheme, req.Host, req.URL.Path)
		if req.URL.RawQuery != "" {
			fullURL += "?" + req.URL.RawQuery
		}

		parsedURL, err := url.Parse(fullURL)
		if err != nil {
			fmt.Printf("❌ 解析URL失败: %v\n", err)
			s.sendHTTPError(clientConn, 400, "Bad Request")
			return
		}
		req.URL = parsedURL
	}

	// 转发请求到目标服务器
	s.forwardHTTPRequest(clientConn, req)
}

// forwardHTTPRequest 转发HTTP请求到目标服务器
func (s *Server) forwardHTTPRequest(clientConn net.Conn, req *http.Request) {
	// 连接到目标服务器
	targetHost := req.URL.Host
	if !strings.Contains(targetHost, ":") {
		if req.URL.Scheme == "https" {
			targetHost += ":443"
		} else {
			targetHost += ":80"
		}
	}

	targetConn, err := net.DialTimeout("tcp", targetHost, 10*time.Second)
	if err != nil {
		fmt.Printf("❌ 连接目标服务器失败: %v\n", err)
		s.sendHTTPError(clientConn, 502, "Bad Gateway")
		return
	}
	defer targetConn.Close()

	// 发送请求到目标服务器
	if err := req.Write(targetConn); err != nil {
		fmt.Printf("❌ 发送请求失败: %v\n", err)
		s.sendHTTPError(clientConn, 502, "Bad Gateway")
		return
	}

	// 读取响应
	resp, err := http.ReadResponse(bufio.NewReader(targetConn), req)
	if err != nil {
		fmt.Printf("❌ 读取响应失败: %v\n", err)
		s.sendHTTPError(clientConn, 502, "Bad Gateway")
		return
	}
	defer resp.Body.Close()

	// 转发响应到客户端
	if err := resp.Write(clientConn); err != nil {
		fmt.Printf("❌ 转发响应失败: %v\n", err)
		return
	}

	fmt.Printf("✅ HTTP请求处理完成: %s %s -> %d\n", req.Method, req.URL.String(), resp.StatusCode)
}

// sendHTTPError 发送HTTP错误响应
func (s *Server) sendHTTPError(conn net.Conn, statusCode int, statusText string) {
	response := fmt.Sprintf("HTTP/1.1 %d %s\r\n", statusCode, statusText)
	response += "Connection: close\r\n"
	response += "Content-Type: text/plain\r\n"
	response += fmt.Sprintf("Content-Length: %d\r\n", len(statusText))
	response += "\r\n"
	response += statusText

	conn.Write([]byte(response))
}
